package main

import (
	"html/template"
	"github.com/gin-gonic/gin"
	"net/http"
	"os"
	"path/filepath"
)
const HTML=`<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文件传输服务器</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        h1 {
            text-align: center;
            margin-bottom: 20px;
        }
        .card {
            border: 1px solid #ddd;
            border-radius: 4px;
            margin-bottom: 20px;
        }
        .card-header {
            background-color: #f7f7f7;
            padding: 10px 15px;
            border-bottom: 1px solid #ddd;
        }
        .card-body {
            padding: 15px;
        }
        table {
            width: 100%;
            border-collapse: collapse;
        }
        table, th, td {
            border: 1px solid #ddd;
        }
        th, td {
            padding: 8px;
            text-align: left;
        }
        th {
            background-color: #f2f2f2;
        }
        .btn {
            display: inline-block;
            padding: 6px 12px;
            margin-bottom: 0;
            font-size: 14px;
            font-weight: 400;
            line-height: 1.42857143;
            text-align: center;
            white-space: nowrap;
            vertical-align: middle;
            cursor: pointer;
            background-image: none;
            border: 1px solid transparent;
            border-radius: 4px;
            text-decoration: none;
        }
        .btn-primary {
            color: #fff;
            background-color: #337ab7;
            border-color: #2e6da4;
        }
        .btn-success {
            color: #fff;
            background-color: #5cb85c;
            border-color: #4cae4c;
        }
        .form-control {
            display: block;
            width: 100%;
            height: 34px;
            padding: 6px 12px;
            font-size: 14px;
            line-height: 1.42857143;
            color: #555;
            background-color: #fff;
            background-image: none;
            border: 1px solid #ccc;
            border-radius: 4px;
        }
        .mb-3 {
            margin-bottom: 15px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>文件传输服务器</h1>
        
        <div class="card">
            <div class="card-header">
                <h5>文件列表</h5>
            </div>
            <div class="card-body">
                <table id="fileTable">
                    <thead>
                        <tr>
                            <th>文件名</th>
                            <th>操作</th>
                        </tr>
                    </thead>
                    <tbody id="fileList">
                        <!-- 文件列表将通过JavaScript动态加载 -->
                    </tbody>
                </table>
            </div>
        </div>

        <div class="card">
            <div class="card-header">
                <h5>上传文件</h5>
            </div>
            <div class="card-body">
                <form id="uploadForm">
                    <div class="mb-3">
                        <input class="form-control" type="file" id="fileInput" required>
                    </div>
                    <button type="submit" class="btn btn-primary">上传</button>
                </form>
            </div>
        </div>
    </div>

    <script>
        // 页面加载时获取文件列表
        document.addEventListener('DOMContentLoaded', function() {
            fetchFileList();
        });

        // 获取文件列表
        function fetchFileList() {
            fetch('/api/files')
                .then(response => response.json())
                .then(files => {
                    const fileList = document.getElementById('fileList');
                    fileList.innerHTML = '';
                    
                    files.forEach(file => {
                        const row = document.createElement('tr');
                        row.innerHTML = "<td>"+file+"</td><td><a href=\"/download/"+file+"\" class=\"btn btn-success\">下载</a></td>";
                        fileList.appendChild(row);
                    });
                });
        }

        // 处理文件上传
        document.getElementById('uploadForm').addEventListener('submit', function(e) {
            e.preventDefault();
            
            const fileInput = document.getElementById('fileInput');
            const formData = new FormData();
            formData.append('file', fileInput.files[0]);
            
            fetch('/upload', {
                method: 'POST',
                body: formData
            })
            .then(response => {
                if (response.ok) {
                    alert('文件上传成功');
                    fileInput.value = '';
                    fetchFileList();
                } else {
                    alert('文件上传失败');
                }
            });
        });
    </script>
</body>
</html>`
func main() {
	r := gin.Default()
	
	// 设置模板目录
	tmpl := template.Must(template.New("index.html").Parse(HTML))

	r.SetHTMLTemplate(tmpl)
	// 创建files目录如果不存在
	if _, err := os.Stat("files"); os.IsNotExist(err) {
		os.Mkdir("files", 0755)
	}
	
	// 路由设置
	r.GET("/", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.html", nil)
	})
	
	// 文件列表API
	r.GET("/api/files", listFilesHandler)
	
	// 文件下载API
	r.GET("/download/:filename", downloadFileHandler)
	
	// 文件上传API
	r.POST("/upload", uploadFileHandler)
	
	// 启动服务器
	r.Run(":52565")
}

func listFilesHandler(c *gin.Context) {
	filesDir := "./files"
	
	// 读取files目录
	entries, err := os.ReadDir(filesDir)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "无法读取文件目录",
		})
		return
	}
	
	// 提取文件名
	var fileNames []string
	for _, entry := range entries {
		if !entry.IsDir() {
			fileNames = append(fileNames, entry.Name())
		}
	}
	
	c.JSON(http.StatusOK, fileNames)
}

func downloadFileHandler(c *gin.Context) {
	filename := c.Param("filename")
	if filename == "" {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "文件名不能为空",
		})
		return
	}

	// 安全处理文件名，防止目录遍历
	safeFilename := filepath.Base(filename)
	filePath := filepath.Join("./files", safeFilename)

	// 检查文件是否存在
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		c.JSON(http.StatusNotFound, gin.H{
			"error": "文件不存在",
		})
		return
	}

	// 设置响应头，触发浏览器下载
	c.Header("Content-Description", "File Transfer")
	c.Header("Content-Disposition", "attachment; filename="+safeFilename)
	c.Header("Content-Type", "application/octet-stream")
	c.Header("Content-Transfer-Encoding", "binary")
	c.Header("Cache-Control", "no-store")

	// 发送文件
	c.File(filePath)
}

func uploadFileHandler(c *gin.Context) {
	// 限制上传文件大小为10MB
	c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 10<<25)
	
	// 获取上传的文件
	file, err := c.FormFile("file")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "获取上传文件失败: " + err.Error(),
		})
		return
	}

	// 验证文件名
	if file.Filename == "" {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "文件名不能为空",
		})
		return
	}

	// 安全处理文件名
	safeFilename := filepath.Base(file.Filename)
	filePath := filepath.Join("./files", safeFilename)

	// 保存文件
	if err := c.SaveUploadedFile(file, filePath); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "保存文件失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message": "文件上传成功",
		"filename": safeFilename,
	})
}
